﻿#region Namespace Declarations

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using Axiom.Collections;
using Axiom.Configuration;
using Axiom.Core;
using Axiom.Graphics;
using Axiom.Math;
using Axiom.Overlays;
using Axiom.Utilities;
using Engine.GuiDANCE.Components;
using Engine.Input;
using MouseButtons = Engine.Input.MouseButtons;
using System.Windows.Forms;

#endregion Namespace Declarations

namespace Engine.GuiDANCE
{
    /// <summary>
    ///     Base class for Axiom examples.
    /// </summary>
    public abstract class GuiBase : IDisposable
    {
        public enum RenderTypes
        {
            Shaded,
            Wireframe,
            PointCloud,
        };

        public GuiBase(Control target)
        {
            userControl = target;
        }

        void userControl_Resize(object sender, EventArgs e)
        {
            window.Resize(userControl.Width, userControl.Height);
        }

        #region Protected Fields

        private bool isClosing;
        public Control userControl; 
        protected Root engine;
        protected Camera camera;
        protected Viewport viewport;
        protected SceneManager scene;
        protected RenderWindow window;
        protected InputReader input;
        
        protected bool showDebugOverlay = false;
        protected float statDelay = 0.0f;
        protected float debugTextDelay = 0.0f;
        protected string debugText = "";
        protected float toggleDelay = 0.0f;
        protected int aniso = 1;
        protected TextureFiltering filtering = TextureFiltering.Bilinear;

        #endregion Protected Fields

        #region Protected Methods

        //protected bool Configure()
        //{
        //    // HACK: Temporary
        //    //RenderSystem renderSystem = engine.RenderSystems[ 0 ];
        //    //engine.RenderSystem = renderSystem;
        //    //EngineConfig.DisplayModeRow mode = renderSystem.ConfigOptions.DisplayMode[ 0 ];
        //    //mode.FullScreen = true;
        //    //mode.Selected = true;

        //    window = engine.Initialize( true, "Axiom Engine Window" );

        //    ShowDebugOverlay( showDebugOverlay );

        //    return true;
        //}

        protected virtual void CreateCamera()
        {
            // create a camera and initialize its position
            camera = scene.CreateCamera("Camera");
            camera.AutoAspectRatio = true;
            //camera.Position = new Vector3(0, 0, 500);
            //camera.LookAt(new Vector3(0, 0, -300));

            //// set the near clipping plane to be very close
            //camera.Near = 5;
        }

        /// <summary>
        ///    Shows the debug overlay, which displays performance statistics.
        /// </summary>
        protected void ShowDebugOverlay(bool show)
        {
            // gets a reference to the default overlay
            Overlay o = OverlayManager.Instance.GetByName("Common/Debug/GUI");

            if (o == null)
            {
                LogManager.Instance.Write(string.Format("Could not find overlay named '{0}'.", "Common/Debug/GUI"));
            }

            if (show)
            {
                o.Show();
            }
            else
            {
                o.Hide();
            }
        }

        protected void TakeScreenshot(string fileName)
        {
            window.WriteContentsToFile(fileName);
        }

        #endregion Protected Methods

        #region Protected Virtual Methods

        protected virtual void ChooseSceneManager()
        {
            // Get the SceneManager, a generic one by default
            scene = engine.CreateSceneManager(SceneType.Generic, "GameSM");
            scene.ClearScene();
        }

        protected virtual void CreateViewports()
        {
            Debug.Assert(window != null, "Attempting to use a null RenderWindow.");
            // create a new viewport and set it's background color
            viewport = window.AddViewport(camera, 0, 0, 1.0f, 1.0f, 100);
            viewport.BackgroundColor = new ColorEx(1, 0.5f, 0.5f, 0.5f);
        }

        protected virtual bool Setup()
        {
            // instantiate the Root singleton
            //engine = new Root( "EngineConfig.xml", "AxiomEngine.log" );
            engine = Root.Instance;

            // add event handlers for frame events
            engine.FrameStarted += new FrameEvent(OnFrameStarted);
            engine.FrameEnded += new FrameEvent(OnFrameEnded);

            window = engine.Initialize(false, "Game Window");

            NamedParameterList windowParams = new NamedParameterList();
            windowParams.Add("externalWindowHandle", userControl.Handle);
            window = engine.CreateRenderWindow("Game Window", 1024, 768, false, windowParams);

            OnCreateWindow();

            ResourceGroupManager.Instance.InitializeAllResourceGroups();
#if (DEBUG)
            showDebugOverlay = true;
#endif
            ShowDebugOverlay(showDebugOverlay);
            ChooseSceneManager();
            CreateCamera();
            CreateViewports();

            // set default mipmap level
            TextureManager.Instance.DefaultMipmapCount = 5;

            // retreive and initialize the input system
            input = new InputReader(userControl);

            // call the overridden CreateScene method
            CreateScene();

            userControl.Resize += new EventHandler(userControl_Resize);
            window.Resize(userControl.Width, userControl.Height);

            return true;
        }

        /// <summary>
        ///		Loads default resource configuration if one exists.
        /// </summary>
        //protected virtual void SetupResources()
        //{
        //    string resourceConfigPath = Path.GetFullPath( "EngineConfig.xml" );

        //    if ( File.Exists( resourceConfigPath ) )
        //    {
        //        EngineConfig config = new EngineConfig();

        //        // load the config file
        //        // relative from the location of debug and releases executables
        //        config.ReadXml( "EngineConfig.xml" );

        //        // interrogate the available resource paths
        //        foreach ( EngineConfig.FilePathRow row in config.FilePath )
        //        {
        //            ResourceManager.AddCommonArchive( row.src, row.type );
        //        }
        //    }
        //}

        #endregion Protected Virtual Methods

        #region Protected Abstract Methods

        /// <summary>
        /// 
        /// </summary>
        protected abstract void CreateScene();

        #endregion Protected Abstract Methods

        #region Public Methods

        public void Start()
        {
            try
            {
                if (Setup())
                {
                    // start the engines rendering loop
                    engine.StartRendering();
                }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
            }
            catch (Exception ex)
            {
                // try logging the error here first, before Root is disposed of
                if (LogManager.Instance != null)
                {
                    LogManager.Instance.Write(LogManager.BuildExceptionString(ex));
                }
            }
        }

        public void Stop()
        {
            isClosing = true;
        }

        public virtual void Dispose()
        {
            if (engine != null)
            {
                // remove event handlers
                engine.FrameStarted -= new FrameEvent(OnFrameStarted);
                engine.FrameEnded -= new FrameEvent(OnFrameEnded);

                //engine.Dispose();
            }
            scene.RemoveAllCameras();
            scene.RemoveCamera(camera);
            camera = null;
            engine.RenderSystem.DetachRenderTarget(window);
            window.Dispose();

            engine.Dispose();
        }

        #endregion Public Methods

        #region Event Handlers

        protected virtual bool OnFrameEnded(Object source, FrameEventArgs e)
        {
            return true;
        }

        protected virtual bool OnFrameStarted(Object source, FrameEventArgs e)
        {
            if (isClosing)
            {
                engine.QueueEndRendering();
                return false;
            }
            mouseCoordinates = GetMouseCoordinates();
            Cursor.OnFrameStarted();
            for (int index = 0; index < Panels.Count; index++)
            {
                Panels[index].OnFrameStarted();
            }
            mouseState = GuiMouseState.PressedNone;
            return true;
        }

        protected void UpdateStats()
        {
            // TODO: Replace with CEGUI
            OverlayElement element = OverlayManager.Instance.Elements.GetElement("Common/Debug/GUI/CurrFps");
            element.Text = string.Format("Current FPS: {0:#.00}", engine.CurrentFPS);

            element = OverlayManager.Instance.Elements.GetElement("Common/Debug/GUI/BestFps");
            element.Text = string.Format("Best FPS: {0:#.00}", engine.BestFPS);

            element = OverlayManager.Instance.Elements.GetElement("Common/Debug/GUI/WorstFps");
            element.Text = string.Format("Worst FPS: {0:#.00}", engine.WorstFPS);

            element = OverlayManager.Instance.Elements.GetElement("Common/Debug/GUI/AverageFps");
            element.Text = string.Format("Average FPS: {0:#.00}", engine.AverageFPS);

            element = OverlayManager.Instance.Elements.GetElement("Common/Debug/GUI/NumTris");
            element.Text = string.Format("Triangle Count: {0}", scene.TargetRenderSystem.FacesRendered);
        }

        protected virtual void OnCreateWindow()
        {
        }

        /// <summary>
        /// Show a text message on screen for two seconds.
        /// </summary>
        /// <param name="text"></param>
        protected void SetDebugText(string text)
        {
            SetDebugText(text, 2.0f);
        }

        /// <summary>
        /// Show a text message on screen for the specified amount of time.
        /// </summary>
        /// <param name="text">Text to show</param>
        /// <param name="delay">Duration in seconds</param>
        protected void SetDebugText(string text, float delay)
        {
            debugText = text;
            debugTextDelay = delay;
        }

        #endregion Event Handlers

        #region Static Methods
        public static GuiCursor Cursor;
        public static List<GuiPanel> Panels = new List<GuiPanel>();
        public static Vector2 Resolution;

        public static GuiRenderBox RenderBox;

        private static RenderWindow renderWindow;
        public static RenderWindow RenderWindow
        {
            get
            {
                return GuiBase.renderWindow;
            }
            set
            {
                GuiBase.renderWindow = value;
                Resolution = new Vector2((float)renderWindow.Width, (float)renderWindow.Height);
            }
        }
        private static Vector2 mouseCoordinates;
        public static Vector2 MouseCoordinates
        {
            get { return GuiBase.mouseCoordinates; }
            set { GuiBase.mouseCoordinates = value; }
        }

        private static Vector2 GetMouseCoordinates()
        {
            Point clientMouse = RenderBox.PointToClient(System.Windows.Forms.Cursor.Position);
            return new Vector2(((float)clientMouse.X / (float)RenderBox.Width) * Resolution.x, ((float)clientMouse.Y / (float)RenderBox.Height) * Resolution.y);
        }

        private static GuiMouseState mouseState;
        public static GuiMouseState MouseState
        {
            get { return mouseState; }
            set { mouseState = value; }
        }

        #endregion
    }
}

